from zdataclass.zdataclass import *
from dataclasses import dataclass
import dataclasses
import crcmod.predefined

# from zdataclass import basedataclass, dataclass, uint8,\
#     dataclasses, uint2, uint12, uint16, uint32, uint64,LENGTH_FIELD, UNION_FIELD,DATA_FIELD
    
#带长度域结构（简单结构）
@dataclass
class s_with_length_field(basedataclass):
    '''
    typedef struct s_with_length_field {
        uint8 length;
        uint8 * data;
    };
    '''
    length: uint8 = dataclasses.field(default=None, metadata={DATA_FIELD: 'data'})
    data: bytearray = dataclasses.field(default_factory=bytearray, metadata={LENGTH_FIELD: 'length', UNION_FIELD: True})

#带联合域结构（复杂结构）
@dataclass
class s_with_union_field(basedataclass):
    '''
    typedef struct s_with_union_field {
        uint16 hci_length;
        union 
        {
           uint8* hci_data;
           struct {
               uint16 l2c_length;
               uint16 cid;
               uint8* l2c_data;
           }l2c;
        };
    };
    hci_data中的field中定义的元数据，存在一个UNION_FIELD：True则表示，
    后续所有element或成员都共享此域存储空间；此处l2c_length、cid、l2c_data都是共享hci_data存储域的；
    另外注意的是其中hci_length取值是依赖于hci_data域的length；而l2c_length取值依赖于l2c_data数据length

    '''
    hci_length: uint16 = dataclasses.field(default=None, metadata={DATA_FIELD: 'hci_data'})
    hci_data: bytearray = dataclasses.field(default_factory=bytearray,
                                            metadata={UNION_FIELD: True, LENGTH_FIELD: 'hci_length'})
    l2c_length: uint16 = dataclasses.field(default=None, metadata={DATA_FIELD: 'l2c_data'})
    cid: uint16 = None
    l2c_data: bytearray = dataclasses.field(default_factory=bytearray,
                                            metadata={UNION_FIELD: True, LENGTH_FIELD: 'l2c_length'})

#通用结构
@dataclass
class s_with_common_field(basedataclass):
    '''
    # C++中结构示例
    typedef struct s_with_common_field {
        uint8 code;
        uint8 size;
        uint8 *data;
        uint16 crc;
    };
    '''
    code: uint8 = 0x01
    size: uint8 = dataclasses.field(default=None, metadata={DATA_FIELD: 'data'})
    data: bytearray = dataclasses.field(default_factory=bytearray, metadata={LENGTH_FIELD: 'size'})
    crc: uint16 = None

#数组域结构
@dataclass
class s_with_int_array(basedataclass):
    '''
    typedef struct s_with_int_array {
        uint8 * uint8_array;
        uint16 * uint16_array;
        uint32 * uint32_array;
    }; 
    '''
    array8: uint8_array = dataclasses.field(default_factory=uint8_array, metadata={LENGTH_FIELD: 2})
    array16: uint16_array = dataclasses.field(default_factory=uint16_array, metadata={LENGTH_FIELD: 2 * 2})
    array32: uint32_array = dataclasses.field(default_factory=uint32_array, metadata={LENGTH_FIELD: 1 * 4})

#带位域域结构（复杂结构）
@dataclass
class s_with_bitfield(basedataclass):
    '''
    union s_with_bitfield{
        uint8 * data;
        struct bitfield{
           uint16:12 handle;
           uint16:2 pd_flag;
           uint16:2 bc_flag;
           uint8 tail;
        };
    }
    '''
    data: bytearray = dataclasses.field(default_factory=bytearray, metadata={LENGTH_FIELD: 4, UNION_FIELD: True})
    head: uint8 = None
    handle: uint12 = None
    pb_flag: uint2 = None
    bc_flag: uint2 = None
    tail:uint8=None

def test_length_field():
    d=s_with_length_field(data=b'\x01\x02')
    print(f'{d},len={len(d)}')
    print(hexlify(d.pack()))

    d2=s_with_length_field().unpack(d.pack())
    print(f'{d2},len={len(d2)}')
    if d2==d:
        print('test_length_field pass .\n')
    else:
        print('test_length_field fail\n') 

def test_union_field():
    d=s_with_union_field(cid=0x0040,l2c_data=b'\x01')
    print(f'{d},len={len(d)}')
    data=d.pack()
    print(hexlify(data))
    d2=s_with_union_field().unpack(data)
    print(f'{d2},len={len(d2)}')
    if d2==d:
        print('test_union_field pass .\n')
    else:
        print('test_union_field fail\n')
def crc16(data):
    # 创建CRC对象并指定CRC标识符为'crc-16'
    crc_func = crcmod.predefined.mkPredefinedCrcFun('crc-16')
    return crc_func(data)


def test_with_common_field():
    payload=b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00'
    crc=crc16(payload)
    d=s_with_common_field(data=payload,crc=crc)
    print(f'{d},len={len(d)}')
    data=d.pack()
    d2=s_with_common_field().unpack(data)
    print(f'{d2},len={len(d2)}')
    print(hexlify(data))

def test_int_array():
    d=s_with_int_array(array8=[0x01,0x02],
                       array16=[0x0002,0x0004],
                       array32=[0x10203040])
    print(f'{d},len={len(d)}')
    data=d.pack()
    print(hexlify(data))
    d2=s_with_int_array().unpack(data)
    print(f'{d2},len={len(d2)}')
    if d2==d:
        print('test_int_array pass .\n')
    else:
        print('test_int_array fail\n')

def test_bitfield():
    d=s_with_bitfield(head=0,pb_flag=1,bc_flag=2,handle=0x20,tail=255)
    print(f'{d},len={len(d)}')
    data=d.pack()
    print(hexlify(data))

    d2=s_with_bitfield().unpack(data)
    print(f'{d2},len={len(d2)}')
    if d2==d:
        print('test_bitfield pass .\n')
    else:
        print('test_bitfield fail\n')


if __name__ == '__main__':
    test_length_field()
    print("union test#####################################################")
    test_union_field()
    print("common test#####################################################")
    test_with_common_field()
    print("int array test#####################################################")
    test_int_array()
    print("bitfield test#####################################################")
    test_bitfield()

